Análise de de boost único¶

Nesta análise vamos partir dos conhecimentos adquiridos na análise de podas do AQE, onde descobrimos que utilizar a ordem do fator de boosting com até cinco termos é o método de poda mais razoável para o caso geral, o qual obteve NDCG@24 de 76,58%. Nesse método, foi fixado o fator de boosting de 0.100 para todos os termos, independente da base utilizada. Agora, vamos experimentar com diferentes fatores de boosting, independente da base utilizada. Vamos experimentar com fatores de boost entre 0 e 0,25.

Carregando libs¶

In [1]:
import json
import yaml
import pandas as pd
import numpy as np
import plotly.express as px

from utils.utils import get_expanded_queries, make_elasticsearch_new_aqe_queries,\
    create_new_expanded_queries, create_new_aqe_validation_dataset, create_new_aqe_metrics,\
    expanded_with_aqe_boost_order
In [2]:
with open("../conf/config.yaml", "r") as yamlfile:
    cfg = yaml.safe_load(yamlfile)
In [3]:
with open("../../dados/regis/regis_queries.json", 'r') as regis_file:
    regis_queries = json.load(regis_file)
In [4]:
regis_queries = get_expanded_queries(regis_queries)
regis_queries[:2]
Out[4]:
[{'title': 'História da geoquímica na Petrobras',
  'query_id': 'Q1',
  'expanded_query': '((História da geoquímica na Petrobras) OR ( (historia^1.000 OR história^0.890 OR history^0.571 OR "histórico do campo"^0.525 OR review^0.159 OR revisão^0.164 OR "histórico de caso"^0.225) OR (geoquimica^1.000 OR geoquímica^0.890 OR geoquímicas^0.691 OR geoquímico^0.672 OR geoquimicos^0.736 OR geoquimicas^0.691 OR geoquimico^0.672 OR geochemistry^0.601 OR "geochemical anomaly"^0.225 OR "geochemical interpretation"^0.225 OR "composição dos sedimentos"^0.225 OR "sediment composition"^0.225 OR geology^0.195 OR geologia^0.253 OR petrochemistry^0.153 OR petroquímica^0.184 OR "geochemical cycle"^0.225 OR petrografia^0.255 OR petrography^0.191 OR "análise de rochas"^0.225 OR "rock analysis"^0.225 OR "composição das rochas"^0.225 OR "rock composition"^0.225 OR transect^0.150 OR "geochemical map"^0.225 OR "geochemical exploration"^0.225 OR "geochemical logging"^0.225 OR geophysics^0.179 OR geofísica^0.256 OR "geochemical data"^0.225) OR petrobras^1.000 ))'},
 {'title': 'Lógica fuzzy aplicada  à industria do petróleo',
  'query_id': 'Q2',
  'expanded_query': '((Lógica fuzzy aplicada à industria do petróleo) OR ( ("logica fuzzy"^1.000 OR "lógica fuzzy"^0.667 OR "lógica difusa"^0.667 OR "logica nebulosa"^0.667 OR "logica difusa"^0.667 OR "fuzzy logic"^0.667) OR ("industria do petroleo"^1.000 OR "indústria do petróleo"^0.667 OR "industria de petroleo"^0.667 OR "petroleum industry"^0.667) OR (logica^1.000 OR lógica^0.890 OR lógico^0.744) OR fuzzy^1.000 OR (aplicada^1.000 OR aplicado^0.795 OR aplicados^0.756) OR (industria^1.000 OR indústria^0.890 OR industry^0.576) OR (petroleo^1.000 OR petróleo^0.890 OR petróleos^0.705 OR petroleos^0.705 OR petroleum^0.632 OR "gasolina natural"^0.525 OR "natural gas"^0.350 OR "gás natural"^0.423 OR "commingled production"^0.525 OR "produção misturada"^0.525 OR "óleo cru"^0.525 OR "crude oil"^0.353 OR "hydrocarbon potential"^0.225 OR "potencial de hidrocarbonetos"^0.225 OR "fluido do reservatório"^0.225 OR "reservoir fluid"^0.225 OR "raw material"^0.225 OR "matéria prima"^0.224 OR "razão de hidrocarbonetos"^0.225 OR "hydrocarbon ratio"^0.225 OR "fossil fuel"^0.150 OR "combustível fóssil"^0.225) ))'}]
In [5]:
ground_truth = pd.read_csv(
    "../../dados/regis/regis_ground_truth.csv"
).rename(
    columns={"relevance": "relevance_ground_truth"}
)
ground_truth.head()
Out[5]:
query_id document_id relevance_ground_truth
0 Q1 BR-BG.03944 1
1 Q1 BR-BG.03925 1
2 Q1 BR-TU.23384 0
3 Q1 BR-TU.12209 0
4 Q1 BR-BG.04089 2

Criando queries com diferentes fatores de boost do AQE¶

Aqui vamos experimentar as expansões de queries com diferentes fatores, variando de 0 até 0,25, com intervalos de 0,001, em conjunto com uma poda com os cinco termos de maior fator estabelecidos pelo AQE.

In [6]:
factors = np.arange(0, 0.25, 0.001).tolist()
all_expanded_queries = list()
for query in regis_queries:
    for factor in factors:
        factor_str = "{:.3f}".format(factor)
        new_expanded_queries = create_new_expanded_queries(
            query["expanded_query"],
            expansion=expanded_with_aqe_boost_order,
            num_termos=[5],
            factor=factor_str
        )
    
        for i, new_expanded_query in new_expanded_queries:
            q = query.copy()
            q["expanded_query"] = new_expanded_query
            q["factor"] = factor_str
            all_expanded_queries.append(q)
all_expanded_queries[:2]
Out[6]:
[{'title': 'História da geoquímica na Petrobras',
  'query_id': 'Q1',
  'expanded_query': '((História da geoquímica na Petrobras) OR ((historia^0.000 OR história^0.000 OR history^0.000 OR "histórico do campo"^0.000 OR review^0.000 OR revisão^0.000 OR "histórico de caso"^0.000) OR (geoquimica^0.000 OR geoquímica^0.000 OR geoquímicas^0.000 OR geoquímico^0.000 OR geoquimicos^0.000 OR geoquimicas^0.000 OR geoquimico^0.000 OR geochemistry^0.000 OR "geochemical anomaly"^0.000 OR "geochemical interpretation"^0.000 OR "composição dos sedimentos"^0.000 OR "sediment composition"^0.000 OR geology^0.000 OR geologia^0.000 OR petrochemistry^0.000 OR petroquímica^0.000 OR "geochemical cycle"^0.000 OR petrografia^0.000 OR petrography^0.000 OR "análise de rochas"^0.000 OR "rock analysis"^0.000 OR "composição das rochas"^0.000 OR "rock composition"^0.000 OR transect^0.000 OR "geochemical map"^0.000 OR "geochemical exploration"^0.000 OR "geochemical logging"^0.000 OR geophysics^0.000 OR geofísica^0.000 OR "geochemical data"^0.000) OR petrobras^0.000 ))',
  'factor': '0.000'},
 {'title': 'História da geoquímica na Petrobras',
  'query_id': 'Q1',
  'expanded_query': '((História da geoquímica na Petrobras) OR ((historia^0.001 OR história^0.001 OR history^0.001 OR "histórico do campo"^0.001 OR review^0.000 OR revisão^0.000 OR "histórico de caso"^0.001) OR (geoquimica^0.001 OR geoquímica^0.001 OR geoquímicas^0.001 OR geoquímico^0.000 OR geoquimicos^0.001 OR geoquimicas^0.001 OR geoquimico^0.000 OR geochemistry^0.000 OR "geochemical anomaly"^0.000 OR "geochemical interpretation"^0.000 OR "composição dos sedimentos"^0.000 OR "sediment composition"^0.000 OR geology^0.000 OR geologia^0.000 OR petrochemistry^0.000 OR petroquímica^0.000 OR "geochemical cycle"^0.000 OR petrografia^0.000 OR petrography^0.000 OR "análise de rochas"^0.000 OR "rock analysis"^0.000 OR "composição das rochas"^0.000 OR "rock composition"^0.000 OR transect^0.000 OR "geochemical map"^0.000 OR "geochemical exploration"^0.000 OR "geochemical logging"^0.000 OR geophysics^0.000 OR geofísica^0.000 OR "geochemical data"^0.000) OR petrobras^0.001 ))',
  'factor': '0.001'}]

Realizando consultas no Elasticsearch¶

Em posse das queries que utilizam cinco termos e fator de boost único, vamos criar o dataset de validação, o qual possui informações do ground truth da base de dados REGIS.

In [7]:
ranking_result_df = make_elasticsearch_new_aqe_queries(
    all_expanded_queries,
    cfg,
    24,
    attrs=["query_id", "factor"]
)
ranking_result_df.head()
Out[7]:
query_id factor document_id relevance_ranking
0 Q1 0.000 BR-BG.03964 9.573541
1 Q1 0.000 BR-BG.03967 9.460924
2 Q1 0.000 BR-BG.04004 9.276192
3 Q1 0.000 BR-TU.20287 9.119863
4 Q1 0.000 BR-BT.05005 9.103277
In [8]:
validation_dataset = create_new_aqe_validation_dataset(
    ranking_result_df,
    ground_truth,
    boost_cols=["factor"]
)
validation_dataset.head()
Out[8]:
query_id factor document_id relevance_ranking relevance_ground_truth evaluated
0 Q1 0.000 BR-BG.03964 9.573541 2.0 True
1 Q1 0.000 BR-BG.03967 9.460924 3.0 True
2 Q1 0.000 BR-BG.04004 9.276192 1.0 True
3 Q1 0.000 BR-TU.20287 9.119863 0.0 True
4 Q1 0.000 BR-BT.05005 9.103277 1.0 True

Análise das consultas no Elasticsearch¶

Agora vamos criar as métricas para cada base de dados e quantidade de termos derivados e visualizar os resultados.

Criando métricas¶

In [9]:
metrics_df = create_new_aqe_metrics(
    validation_dataset,
    boost_cols=["factor"]
)
metrics_df.head()
Out[9]:
query_id factor ndcg@24 ap@24 eval_prop
0 Q1 0.000 0.766699 0.355878 0.944444
1 Q1 0.001 0.766699 0.355878 0.944444
2 Q1 0.002 0.766699 0.355878 0.944444
3 Q1 0.003 0.769555 0.355489 0.944444
4 Q1 0.004 0.769555 0.355489 0.944444

Avaliando métricas¶

Vamos agora avaliar as métricas. Vamos utilizar as seguintes métricas:

  • ndcg - Normalized Discounted Cumulative Gain
  • map - Mean Average Precision
  • eval_prop - Proporção de documentos avaliados

Vejamos qual o melhor fator de boost, utilizando a média dos NDCG@24:

In [10]:
data_viz = metrics_df.groupby(
    "factor"
).agg(
    mean_ndcg = ("ndcg@24", "mean")
).reset_index()

fig = px.line(
    data_viz,
    x="factor",
    y="mean_ndcg",
    labels={
        "factor": "Fator de boost",
        "mean_ndcg": "NDCG@24 médio",
    },
    markers=True,
    title="NDCG@24 médio para cada fator de boost"
)
fig.show()

Podemos ver que os fatores de boost único mais interessantes, independente da base de dados, ficam entre 0,006 e 0,070. O fator de boost único que obteve melhor resultado foi 0,026, o qual obteve NDCG@24 médio de 77,24%.

Vejamos agora os resultados individuais das queries:

In [11]:
metrics_df_factor = metrics_df.query(
    "factor == '0.026'"
)

data_viz = metrics_df.query(
    "factor == '0.026'"
).sort_values(
    ["ndcg@24"], ascending=False
)

fig = px.bar(
    data_viz,
    x="query_id",
    y="ndcg@24",
    labels={
        "query_id": "Query ID",
        "ndcg@24": "NDCG@24",
    },
)
fig.show()

Podemos ver que mais de metade das queries possuem NDCG@24 acima de 0,8, e que apenas seis das 34 queries possuem valores de NDCG@24 abaixo de 0,6, onde três delas possuem valores abaixo de 0,4.

Conclusão¶

Nesta análise experimentamos diferentes fatores de boost único entre 0 e 0,25, independente da base de dados, precedidos de uma poda com os cinco termos de maior relevância, definida pelo AQE.

O fator de boost único 0.026 se mostrou o valor mais razoável, atingindo um NDCG@24 de 77,24%. A nível comparativo, o Elasticsearch puro resulta em um NDCG@24 de 76,03%, utilizar apenas os fatores de multiplicação dos boosts resulta em um NDCG@24 de 77,97%, utilizar o mecanismo de poda com cinco termos derivados resulta em um NDCG@24 de 76,58%, enquanto utilizar os fatores de multiplicação dos boosts em conjunto com o mecanismo de poda com cinco termos derivados resulta em um NDCG@24 de 78,33%. Apesar da abordagem dessa análise atingir um valor de NDCG@24 inferior a outras abordagens ela traz a vantagem de ser bem mais simplificada, visto que utiliza apenas um fator único, independente da base, trazendo celeridade na implementação do AQE.